/**
 * Copyright (c) 2024 Hunan OpenValley Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "GPUImageColorMatrixFilter.h"

const std::string GPUImageColorMatrixFilter::COLOR_MATRIX_FRAGMENT_SHADER = R"(
    #extension GL_OES_EGL_image_external : require
    varying highp vec2 textureCoordinate;

    uniform samplerExternalOES inputImageTexture;

    uniform lowp mat4 colorMatrix;
    uniform lowp float intensity;

    void main()
    {
        lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
        lowp vec4 outputColor = textureColor * colorMatrix;

        gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);
    }
)";

GPUImageColorMatrixFilter::GPUImageColorMatrixFilter()
{
    intensity = 1.0f;
    colorMatrix = new float[16]{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                                0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
}

GPUImageColorMatrixFilter::~GPUImageColorMatrixFilter()
{
    if (colorMatrix != nullptr) {
        delete[] colorMatrix;
        colorMatrix = nullptr;
    }
}

GPUImageColorMatrixFilter::GPUImageColorMatrixFilter(float intensityValue,
                                                     float *matrix)
    : GPUImageFilter(NO_FILTER_VERTEX_SHADER, COLOR_MATRIX_FRAGMENT_SHADER)
{
    intensity = intensityValue;
    colorMatrix = matrix;
}

void GPUImageColorMatrixFilter::onInit()
{
    GPUImageFilter::onInit();
    colorMatrixLocation = glGetUniformLocation(getProgram(), "colorMatrix");
    intensityLocation = glGetUniformLocation(getProgram(), "intensity");
}

void GPUImageColorMatrixFilter::onInitialized()
{
    GPUImageFilter::onInitialized();
    setIntensity(intensity);
    setColorMatrix(colorMatrix);
}

void GPUImageColorMatrixFilter::setIntensity(const float intensityValue)
{
    intensity = intensityValue;
    setFloat(intensityLocation, intensity);
}

void GPUImageColorMatrixFilter::setColorMatrix(float *matrix)
{
    colorMatrix = matrix;
    setUniformMatrix4f(colorMatrixLocation, colorMatrix);
}